#include <stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<signal.h>

int main()
{
    //创建监听快捷字
    int listenfd=socket(PF_INET,SOCK_STREAM,0);

    //本程序的IP地址和端口号
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;//IPv4地址（地址类型）
    addr.sin_port = htons(80);//端口号（网络字节序）,如果程序使用小于1024的端口号需要使用管理员权限（root权限）
    addr.sin_addr.s_addr = htonl(INADDR_ANY);//操作系统在所有的地址进行监听，绑定本机的所有IP地址
    //addr.sin_addr.s_addr = inet_addr("192.168.1.111");//指定一个有线或无线网卡的IP地址进行监听

    //将IP地址与监听套接字进行绑定
    int error = bind(listenfd,(struct sockaddr*)&addr,sizeof (addr));
    if(error)
    {
        //perror函数用于打印错误原因
        perror("bind");
        return 1;
    }

    error = listen(listenfd,3);
    if(error)
    {
        perror("listen");
        return 2;
    }
    //忽略SIGPIPE信号，防止发送数据时被OS终止
    signal(SIGPIPE,SIG_IGN);

    printf("server start\n");
    //循环服务器
    while (1)
    {
    struct sockaddr_in client_addr;
    socklen_t addrlen = sizeof (client_addr);
    //等待客户端连接
    int connectfd = accept(listenfd,(struct sockaddr*)&client_addr,&addrlen);
    printf("client is connected,ip: %s, port: %d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));


    //使用标准IO函数与客户端通信，需要将连接套接字与标准IO文件流绑定
    FILE* fp = fdopen(connectfd,"r+");

    char line[80];
    //循环接收客户端的输入
    while (1)
    {
        //读取客户端发送的请求报文的头部，读到空行为止
    while (fgets(line, sizeof (line),fp))
    {
      if (line[0] == '\r')
      {
          break;
      }
    }

    //给客户端发送响应报文
    fprintf(fp,"HTTP/1.1 200 OK \r\n" );
    fprintf(fp,"Content-Type:text/plain;charset=utf-8\r\n");
    fprintf(fp,"Content-Length:15 \r\n");
    fprintf(fp,"\r\n");
    fprintf(fp,"你好世界！");
    }
    //断开客户端的TCP连接
    fclose(fp);
    }
    return 0;
}
